<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-hemisu.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-hemisu.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-hemisu.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="读书笔记,js高程,">










<meta name="description" content="[TOC] 本章内容 使用XMLHttpRequest对象 使用XMLHttpRequest事件 跨域Ajax通信的限制">
<meta name="keywords" content="读书笔记,js高程">
<meta property="og:type" content="article">
<meta property="og:title" content="js高程读书笔记 第21章 Ajax与Comet">
<meta property="og:url" content="http://www.hemisu.com/2017/09/06/307/index.html">
<meta property="og:site_name" content="何米酥`s Blog">
<meta property="og:description" content="[TOC] 本章内容 使用XMLHttpRequest对象 使用XMLHttpRequest事件 跨域Ajax通信的限制">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2017-11-07T22:07:58.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="js高程读书笔记 第21章 Ajax与Comet">
<meta name="twitter:description" content="[TOC] 本章内容 使用XMLHttpRequest对象 使用XMLHttpRequest事件 跨域Ajax通信的限制">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":true,"scrollpercent":true,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://www.hemisu.com/2017/09/06/307/">





  <title>js高程读书笔记 第21章 Ajax与Comet | 何米酥`s Blog</title>
  








  <!-- Hotjar Tracking Code for www.hemisu.com -->
  <script>
      (function(h,o,t,j,a,r){
          h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
          h._hjSettings={hjid:1933736,hjsv:6};
          a=o.getElementsByTagName('head')[0];
          r=o.createElement('script');r.async=1;
          r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
          a.appendChild(r);
      })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
  </script>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">何米酥`s Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">EFE</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.hemisu.com/2017/09/06/307/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="何米酥">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="何米酥`s Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">js高程读书笔记 第21章 Ajax与Comet</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-09-06T12:26:00+00:00">
                2017-09-06
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/笔记/" itemprop="url" rel="index">
                    <span itemprop="name">笔记</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>[TOC]</p>
<h1 id="本章内容"><a href="#本章内容" class="headerlink" title="本章内容"></a>本章内容</h1><ul>
<li>使用XMLHttpRequest对象</li>
<li>使用XMLHttpRequest事件</li>
<li>跨域Ajax通信的限制</li>
</ul>
<a id="more"></a>
<h1 id="XMLHttpReques对象"><a href="#XMLHttpReques对象" class="headerlink" title="XMLHttpReques对象"></a>XMLHttpReques对象</h1><p>支持IE7以前的版本，创建XMLHttpRequest对象<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createXHR</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> XMLHttpRequest != <span class="string">"undefined"</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> ActiveXObject != <span class="string">"undefined"</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">arguments</span>.callee.activeXString != <span class="string">"string"</span>)&#123;</span><br><span class="line">            <span class="keyword">var</span> versions = [<span class="string">"MSXML2.XMLHttp.6.0"</span>, <span class="string">"MSXML2.XMLHttp.3.0"</span>,</span><br><span class="line">                            <span class="string">"MSXML2.XMLHttp"</span>],</span><br><span class="line">                i, len;</span><br><span class="line">    </span><br><span class="line">            <span class="keyword">for</span> (i=<span class="number">0</span>,len=versions.length; i &lt; len; i++)&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="keyword">new</span> ActiveXObject(versions[i]);</span><br><span class="line">                    <span class="built_in">arguments</span>.callee.activeXString = versions[i];</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125; <span class="keyword">catch</span> (ex)&#123;</span><br><span class="line">                    <span class="comment">//skip</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">     </span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> ActiveXObject(<span class="built_in">arguments</span>.callee.activeXString);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">"No XHR object available."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"example.txt"</span>, <span class="literal">false</span>);</span><br><span class="line">xhr.send(<span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">    alert(xhr.statusText);</span><br><span class="line">    alert(xhr.responseText);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>至此，可以用以下代码创建XHR对象了<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xhr = createXHR();</span><br></pre></td></tr></table></figure></p>
<h2 id="XHR的用法"><a href="#XHR的用法" class="headerlink" title="XHR的用法"></a>XHR的用法</h2><p>使用XHR对象时，要调用的第一个方法是open()，它接受3个参数：要发送的请求的类型、请求的URL和表示是否异步发送请求的布尔值。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"example.php"</span>, <span class="string">"false"</span>);</span><br></pre></td></tr></table></figure></p>
<ul>
<li>URL相对于执行代码的当前页面；</li>
<li>调用open()方法并不会真正发送请求</li>
</ul>
<p>要发送特定的请求，必须调用send()方法。</p>
<p>请求是同步的，JavaScript代码会等到服务器响应之后再继续执行。在收到响应后，响应的数据会自动填充xhr对象的属性：</p>
<ul>
<li>responseText： 作为响应主体被返回的文本。</li>
<li>responseXML： 如果响应的内容类型是”text/xml”或”application/xml”，这个属性中将保存包含着响应数据的XML DOM文档。</li>
<li>status： 响应的HTTP状态。</li>
<li>statusText： HTTP状态的说明。</li>
</ul>
<p>状态码为304表示请求的资源并没有被修改，可以直接使用浏览器中缓存的版本。</p>
<p>所以应该向下列代码检查状态码：<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">    alert(xhr.statusText);</span><br><span class="line">    alert(xhr.responseText);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>如果要发送异步请求，可以检测XHR对象的readyState属性，该属性表示请求/响应过程的当前活动阶段：</p>
<ul>
<li>0: 未初始化。尚未调用open()方法</li>
<li>1: 启动。已经调用open()方法但尚未调用send()方法</li>
<li>2：发送。已经调用send()方法但尚未接收到响应。</li>
<li>3：接受。已经接受到部分响应数据。</li>
<li>4：完成。已经接受到全部响应数据，而且可以在客户端使用了。</li>
</ul>
<p>readyState属性的值由一个值变成另一个值，都触发一次readystatechange事件。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">xhr.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (xhr.readyState == <span class="number">4</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">            alert(xhr.responseText);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"example.txt"</span>, <span class="literal">true</span>);</span><br><span class="line">xhr.send(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure>
<blockquote>
<p>这个例子在onreadystatechange事件处理程序中使用了xhr对象，没有使用this对象，原因是onreadystatechange事件处理程序的作用域问题。如果使用this对象，在有的浏览器中会导致函数执行失败，或者导致错误发生。因此使用实际的XHR对象实例变量是较为可靠的一种方式。</p>
</blockquote>
<h2 id="HTTP头部信息"><a href="#HTTP头部信息" class="headerlink" title="HTTP头部信息"></a>HTTP头部信息</h2><p>默认情况下，在发送XHR请求的同时，还会发送下列头部信息。</p>
<ul>
<li>Accept: 浏览器能够处理的内容类型</li>
<li>Accept-Charset：浏览器能够显示的字符集。</li>
<li>Accept-Encoding:浏览器能够处理的压缩编码。</li>
<li>Accept-Language:浏览器当前设置的语言</li>
<li>Connection：浏览器与服务器之间连接的类型</li>
<li>Host：发出请求的页面所在的域。</li>
<li>Referer：发出请求的页面URI（正确拼法是Referrer）</li>
<li>User-Agent：浏览器的用户代理字符串</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">xhr.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (xhr.readyState == <span class="number">4</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">            alert(xhr.responseText);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"example.php"</span>, <span class="literal">true</span>);</span><br><span class="line">xhr.setRequestHeader(<span class="string">"MyHeader"</span>, <span class="string">"MyValue"</span>);</span><br><span class="line">xhr.send(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure>
<p>使用setRequestHeader()方法可以设置自定义的请求头部信息。</p>
<p>调用xhr对象的getResponseHeader()方法并传入头部字段名称，可以取得相应的相应头部信息。而调用getAllResponseHeaders()方法可以取得一个包含所有头部信息的长字符串。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> myHeader = xhr.getResponseHeader(<span class="string">"MyHeader"</span>);</span><br><span class="line"><span class="keyword">var</span> allHeaders = xhr.getAllRespnseHeaders();</span><br></pre></td></tr></table></figure></p>
<h2 id="GET请求"><a href="#GET请求" class="headerlink" title="GET请求"></a>GET请求</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"example.php?name1=value1&amp;name2=value2"</span>, <span class="literal">true</span>);</span><br></pre></td></tr></table></figure>
<p>这样经常会发生一个错误，就是查询字符串的格式有问题。</p>
<p>查询字符串中每个参数的名值对都必须使用encodeURIComponent()进行编码，然后才能放到URL末尾。</p>
<p>下面这个函数可以辅助向现有URL的末尾添加查询字符串参数。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">addURLParam</span>(<span class="params">url, name, value</span>)</span>&#123;</span><br><span class="line">    url += (url.indexOf(<span class="string">"?"</span>)) == <span class="number">-1</span>? <span class="string">"?"</span> : <span class="string">"&amp;"</span>;</span><br><span class="line">    url += <span class="built_in">encodeURIComponent</span>(name) + <span class="string">"="</span> + <span class="built_in">encodeURIComponent</span>(value);</span><br><span class="line">    <span class="keyword">return</span> url;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="POST请求"><a href="#POST请求" class="headerlink" title="POST请求"></a>POST请求</h2><p>发送post请求，要讲content-type头部信息设置application/x-www-form-urlencoded，也就是表单提交时内容类型，其次是以适当创建一个字符串。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">serialize</span>(<span class="params">form</span>)</span>&#123;        </span><br><span class="line">    <span class="keyword">var</span> parts = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line">    <span class="keyword">var</span> field = <span class="literal">null</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">0</span>, len=form.elements.length; i &lt; len; i++)&#123;</span><br><span class="line">        field = form.elements[i];</span><br><span class="line">    </span><br><span class="line">        <span class="keyword">switch</span>(field.type)&#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">"select-one"</span>:</span><br><span class="line">            <span class="keyword">case</span> <span class="string">"select-multiple"</span>:</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">var</span> j=<span class="number">0</span>, optLen = field.options.length; j &lt; optLen; j++)&#123;</span><br><span class="line">                    <span class="keyword">var</span> option = field.options[j];</span><br><span class="line">                    <span class="keyword">if</span> (option.selected)&#123;</span><br><span class="line">                        <span class="keyword">var</span> optValue = <span class="string">""</span>;</span><br><span class="line">                        <span class="keyword">if</span> (option.hasAttribute)&#123;</span><br><span class="line">                            optValue = (option.hasAttribute(<span class="string">"value"</span>) ? </span><br><span class="line">                                        option.value : option.text);</span><br><span class="line">                        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                            optValue = (option.attributes[<span class="string">"value"</span>].specified ? </span><br><span class="line">                                        option.value : option.text);</span><br><span class="line">                        &#125;</span><br><span class="line">                        parts.push(<span class="built_in">encodeURIComponent</span>(field.name) + <span class="string">"="</span> + </span><br><span class="line">                                   <span class="built_in">encodeURIComponent</span>(optValue));</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">                </span><br><span class="line">            <span class="keyword">case</span> <span class="literal">undefined</span>:     <span class="comment">//fieldset</span></span><br><span class="line">            <span class="keyword">case</span> <span class="string">"file"</span>:        <span class="comment">//file input</span></span><br><span class="line">            <span class="keyword">case</span> <span class="string">"submit"</span>:      <span class="comment">//submit button</span></span><br><span class="line">            <span class="keyword">case</span> <span class="string">"reset"</span>:       <span class="comment">//reset button</span></span><br><span class="line">            <span class="keyword">case</span> <span class="string">"button"</span>:      <span class="comment">//custom button</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">                </span><br><span class="line">            <span class="keyword">case</span> <span class="string">"radio"</span>:       <span class="comment">//radio button</span></span><br><span class="line">            <span class="keyword">case</span> <span class="string">"checkbox"</span>:    <span class="comment">//checkbox</span></span><br><span class="line">                <span class="keyword">if</span> (!field.checked)&#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">/* falls through */</span></span><br><span class="line">                            </span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                parts.push(<span class="built_in">encodeURIComponent</span>(field.name) + <span class="string">"="</span> + </span><br><span class="line">                    <span class="built_in">encodeURIComponent</span>(field.value));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;        </span><br><span class="line">    <span class="keyword">return</span> parts.join(<span class="string">"&amp;"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">submitData</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">    xhr.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (xhr.readyState == <span class="number">4</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">                alert(xhr.responseText);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    xhr.open(<span class="string">"post"</span>, <span class="string">"postexample.php"</span>, <span class="literal">true</span>);</span><br><span class="line">    xhr.setRequestHeader(<span class="string">"Content-Type"</span>, <span class="string">"application/x-www-form-urlencoded"</span>);</span><br><span class="line">    <span class="keyword">var</span> form = <span class="built_in">document</span>.getElementById(<span class="string">"user-info"</span>);            </span><br><span class="line">    xhr.send(serialize(form));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>文件postexample.php可以通过_$POST获取数据<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    header(<span class="string">"Content-Type: text/plain"</span>);   </span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&lt;&lt;&lt;EOF</span></span><br><span class="line"><span class="string">Name: <span class="subst">&#123;$_POST['user-name']&#125;</span></span></span><br><span class="line"><span class="string">Email: <span class="subst">&#123;$_POST['user-email']&#125;</span></span></span><br><span class="line"><span class="string">EOF;</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<blockquote>
<p>text/html与text/plain区别如下：</p>
<ol>
<li>text/html是html格式的正文，text/html的意思是将文件的content-type设置为text/html的形式 </li>
<li>text/plain是无格式正文，text/plain的意思是将文件设置为纯文本的形式，浏览器在获取到这种文件时并不会对其进行处理。</li>
<li>text/xml忽略xml头所指定编码格式而默认采用us-ascii编码</li>
<li>application/xml会根据xml头指定的编码格式来编码</li>
</ol>
</blockquote>
<p>如果不设置Content-Type头部信息，那么发送给服务器的数据就不会出现在$_POST超级全局变量中。</p>
<h1 id="XMLHttpRequest-2级"><a href="#XMLHttpRequest-2级" class="headerlink" title="XMLHttpRequest 2级"></a>XMLHttpRequest 2级</h1><h2 id="FromData"><a href="#FromData" class="headerlink" title="FromData"></a>FromData</h2><p>FromData为序列化表单以及创建与表单格式相同的数据提供便利。</p>
<p>下面代码创建了一个FromData对象，并向其中添加了一些数据。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> data = <span class="keyword">new</span> FromData();</span><br><span class="line">data.append(<span class="string">"name"</span>, <span class="string">"Nicholas"</span>);</span><br></pre></td></tr></table></figure></p>
<p>可以用FromData代替序列化函数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">submitData</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">    xhr.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (xhr.readyState == <span class="number">4</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">                alert(xhr.responseText);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    xhr.open(<span class="string">"post"</span>, <span class="string">"postexample.php"</span>, <span class="literal">true</span>);</span><br><span class="line">    <span class="keyword">var</span> form = <span class="built_in">document</span>.getElementById(<span class="string">"user-info"</span>);            </span><br><span class="line">    xhr.send(<span class="keyword">new</span> FormData(form));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>同时可以不必明确地在XHR对象上设置请求头部。</p>
<h2 id="超时设定"><a href="#超时设定" class="headerlink" title="超时设定"></a>超时设定</h2><p>IE8为XHR对象添加了一个timeout属性，表示请求在等待响应多少毫秒之后就终止。如果在规定的时间内浏览器还没有接收到响应，那么就会触发timeout事件，进而会调用ontimeout事件处理程序。这项功能已经被收入到XMLHttpRequest2规范中。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">xhr.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (xhr.readyState == <span class="number">4</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">                alert(xhr.responseText);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (ex)&#123;</span><br><span class="line">        <span class="comment">//assume handled by ontimeout</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"timeout.php"</span>, <span class="literal">true</span>);</span><br><span class="line">xhr.timeout = <span class="number">1000</span>;</span><br><span class="line">xhr.ontimeout = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    alert(<span class="string">"Request did not return in a second."</span>);</span><br><span class="line">&#125;;        </span><br><span class="line">xhr.send(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure></p>
<h2 id="overrideMimeType-方法"><a href="#overrideMimeType-方法" class="headerlink" title="overrideMimeType()方法"></a>overrideMimeType()方法</h2><p>用于重写XHR响应的MIME类型，比如服务器返回的MIME类型是text/plain，但数据中实际包含的是XML。根据MIME类型，即使数据是XML，responseXML属性中还是null。通过这个overrideMimeType()方法，可以保证把响应当做XML而非纯文本来处理。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xhr = createXHR();</span><br><span class="line">xhr.open(<span class="string">"get"</span>, <span class="string">"text.php"</span>, <span class="literal">true</span>);</span><br><span class="line">xhr.overrideMimeType(<span class="string">"text/xml"</span>);</span><br><span class="line">xhr.send(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure></p>
<h1 id="进度事件-Progress-Events"><a href="#进度事件-Progress-Events" class="headerlink" title="进度事件 Progress Events"></a>进度事件 Progress Events</h1><ul>
<li>loadstrart： 在接收到响应数据的第一个字节时触发。</li>
<li>progress： 在接收响应期间持续不断地触发。</li>
<li>error: 在请求发生错误时触发</li>
<li>abort： 在因为调用abort()方法而终止连接时触发。</li>
<li>load： 在接收到完整的响应数据时触发。</li>
<li>loadend： 在通信完成或者触发error、abort或load事件后触发。</li>
</ul>
<h2 id="load事件"><a href="#load事件" class="headerlink" title="load事件"></a>load事件</h2><p>用于替代readystatechange事件。onload事件处理程序会接收到一个event对象，其target属性就指向XHR对象实例，因而可以访问到XHR对象的所有方法和属性。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">    xhr.onload = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || </span><br><span class="line">                xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">            alert(xhr.responseText);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            alert(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    xhr.open(<span class="string">"get"</span>, <span class="string">"altevents.php"</span>, <span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">    xhr.send(<span class="literal">null</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<p>并非所有的浏览器都为这个事件实现了适当的事件对象，所以还是采用XHR对象变量。</p>
<h2 id="progress事件"><a href="#progress事件" class="headerlink" title="progress事件"></a>progress事件</h2><p>这个事件会在浏览器接收新数据期间周期性地触发。<br>onprogress事件处理程序会接收到一个event对象，其target属性是XHR对象，但包含着三个额外的属性：lengthComputable、position和totalSize。第一个表示进度信息是否可用的布尔值，第二个表示已经接受的字节数，第三个表示根据Content_Length响应头部确定的预期字节数。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> xhr = createXHR();        </span><br><span class="line">    xhr.onload = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span> ((xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span>) || </span><br><span class="line">                xhr.status == <span class="number">304</span>)&#123;</span><br><span class="line">            <span class="built_in">console</span>.log(xhr.responseText);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">"Request was unsuccessful: "</span> + xhr.status);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    xhr.onprogress = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">var</span> divStatus = <span class="built_in">document</span>.getElementById(<span class="string">"status"</span>);</span><br><span class="line">        <span class="keyword">if</span> (event.lengthComputable)&#123;</span><br><span class="line">            divStatus.innerHTML = <span class="string">"Received "</span> + event.position + <span class="string">" of "</span> + event.totalSize + <span class="string">" bytes"</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    xhr.open(<span class="string">"get"</span>, <span class="string">"altevents.php"</span>, <span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">    xhr.send(<span class="literal">null</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<h1 id="跨资源共享-CORS"><a href="#跨资源共享-CORS" class="headerlink" title="跨资源共享 CORS"></a>跨资源共享 CORS</h1><p>在发送请求时，需要给它附加一个额外的Origin头部，其中包含请求页面的源信息，以便服务器根据这个头部信息来决定是否给予响应。</p>
<p>如果服务器认为这个请求可以接受，就在Access-Control_Allow-Origin头部中发相同的源信息。</p>
<h2 id="IE对CORS的实现"><a href="#IE对CORS的实现" class="headerlink" title="IE对CORS的实现"></a>IE对CORS的实现</h2><ul>
<li>cookie不会随请求发送，也不会随响应返回</li>
<li>只能设置请求头部信息中的Content-Type字段</li>
<li>不能访问响应头部信息</li>
<li>只支持GET和POST请求</li>
</ul>
<p>所有的XDR(XDomainRequest)类型都是异步执行的，不能用它来创建同步请求。请求返回之后，会触发load事件，响应的数据也会保存在responseText属性中。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> xdr = <span class="keyword">new</span> XDomainRequest();</span><br><span class="line">xdr.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    alert(xdr.responseText);</span><br><span class="line">&#125;;</span><br><span class="line">xdr.onerror = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    alert(<span class="string">"Error!"</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//you'll need to replace this URL with something that works</span></span><br><span class="line">xdr.open(<span class="string">"get"</span>, <span class="string">"http://www.somewhere-else.com/xdr.php"</span>);</span><br><span class="line">xdr.send(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure>
<h2 id="其他浏览器对CORS的实现"><a href="#其他浏览器对CORS的实现" class="headerlink" title="其他浏览器对CORS的实现"></a>其他浏览器对CORS的实现</h2><p>只需要在open()方法中传入绝对URL即可。</p>
<p>限制：</p>
<ul>
<li>不能使用setRequestHeader()设置自定义头部</li>
<li>不能发送和接受cookie</li>
<li>调用getAllResponseHeaders()方法总会返回空字符串</li>
</ul>
<h2 id="Preflighted-Reqeusts"><a href="#Preflighted-Reqeusts" class="headerlink" title="Preflighted Reqeusts"></a>Preflighted Reqeusts</h2><p>CORS通过一种叫做PreFlighted Requests的透明服务器验证机制支持使用自定义头部、get和post之外的方法以及不同类型的主体内容。</p>
<h2 id="带凭据的请求"><a href="#带凭据的请求" class="headerlink" title="带凭据的请求"></a>带凭据的请求</h2><p>默认情况下，跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true，可以指定某个请求应该发送凭据。</p>
<p>服务器如果接受带凭据的请求，会响应</p>
<p><code>Access-Control-Allow-Credentials: true</code></p>
<p>如果发送的是带凭据的请求，但服务器的响应中没有包含这个头部，那么浏览器就不会把响应交给JavaScript。</p>
<h2 id="跨浏览器的CORS"><a href="#跨浏览器的CORS" class="headerlink" title="跨浏览器的CORS"></a>跨浏览器的CORS</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createCORSRequest</span>(<span class="params">method, url</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">    <span class="keyword">if</span> (<span class="string">"withCredentials"</span> <span class="keyword">in</span> xhr)&#123;</span><br><span class="line">        xhr.open(method, url, <span class="literal">true</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> XDomainRequest != <span class="string">"undefined"</span>)&#123;</span><br><span class="line">        xhr = <span class="keyword">new</span> XDomainRequest();</span><br><span class="line">        xhr.open(method, url);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        xhr = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> xhr;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> request = createCORSRequest(<span class="string">"get"</span>, <span class="string">"http://www.somewhere-else.com/xdr.php"</span>);</span><br><span class="line"><span class="keyword">if</span> (request)&#123;</span><br><span class="line">    request.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="comment">//do something with request.responseText</span></span><br><span class="line">    &#125;;</span><br><span class="line">    request.send();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="其他跨域技术"><a href="#其他跨域技术" class="headerlink" title="其他跨域技术"></a>其他跨域技术</h1><h2 id="图像ping"><a href="#图像ping" class="headerlink" title="图像ping"></a>图像ping</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> img = <span class="keyword">new</span> Image();</span><br><span class="line">img.onload = img.onerror = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    alert(<span class="string">"Done!"</span>);</span><br><span class="line">&#125;;</span><br><span class="line">img.src = <span class="string">"http://www.example.com/test?name=Nicholas"</span>;</span><br></pre></td></tr></table></figure>
<p>图像ping最常用于跟踪用户点击页面或动态广告曝光次数。图像ping有两个主要的缺点：</p>
<ul>
<li>只能发送get请求</li>
<li>无法访问服务器的响应文本。</li>
</ul>
<p>因此，图像ping只能用于浏览器与服务器的单向通信。</p>
<h2 id="JSONP-JSON-with-padding"><a href="#JSONP-JSON-with-padding" class="headerlink" title="JSONP (JSON with padding)"></a>JSONP (JSON with padding)</h2><p>包含在函数调用中的JSON</p>
<p>像这样<br><code>callback({ &quot;name&quot;: &quot;Nicholas&quot;;});</code></p>
<p>JSONP由两部分组成：回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名称一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">handleResponse</span>(<span class="params">response</span>)</span>&#123;</span><br><span class="line">    alert(<span class="string">"You're at IP address "</span> + response.ip + <span class="string">", which is in "</span> + response.city + <span class="string">", "</span> + response.region_name);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> script = <span class="built_in">document</span>.createElement(<span class="string">"script"</span>);</span><br><span class="line">script.src = <span class="string">"http://freegeoip.net/json/?callback=handleResponse"</span>;</span><br><span class="line"><span class="built_in">document</span>.body.insertBefore(script, <span class="built_in">document</span>.body.firstChild);</span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createStreamingClient</span>(<span class="params">url, progress, finished</span>)</span>&#123;        </span><br><span class="line">            </span><br><span class="line">    <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest(),</span><br><span class="line">        received = <span class="number">0</span>;</span><br><span class="line">        </span><br><span class="line">    xhr.open(<span class="string">"get"</span>, url, <span class="literal">true</span>);</span><br><span class="line">    xhr.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">var</span> result;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span> (xhr.readyState == <span class="number">3</span>)&#123;</span><br><span class="line">        </span><br><span class="line">            <span class="comment">//get only the new data and adjust counter</span></span><br><span class="line">            result = xhr.responseText.substring(received);</span><br><span class="line">            received += result.length;</span><br><span class="line">            </span><br><span class="line">            <span class="comment">//call the progress callback</span></span><br><span class="line">            progress(result);</span><br><span class="line">            </span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (xhr.readyState == <span class="number">4</span>)&#123;</span><br><span class="line">            finished(xhr.responseText);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    xhr.send(<span class="literal">null</span>);</span><br><span class="line">    <span class="keyword">return</span> xhr;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> client = createStreamingClient(<span class="string">"streaming.php"</span>, <span class="function"><span class="keyword">function</span>(<span class="params">data</span>)</span>&#123;</span><br><span class="line">                alert(<span class="string">"Received: "</span> + data);</span><br><span class="line">             &#125;, <span class="function"><span class="keyword">function</span>(<span class="params">data</span>)</span>&#123;</span><br><span class="line">                alert(<span class="string">"Done!"</span>);</span><br><span class="line">             &#125;);</span><br></pre></td></tr></table></figure>
<p>通过侦听readystatechange事件及检测readyState的值是否为3，就可以利用XHR对象实现HTTP流。在上述这些浏览器中，随着不断从服务器接收数据，readyState的值会周期性地变为3。当readyState值变为3时，responseText属性中就会保存接收到的所有数据。</p>
<p>createSteamingClient()函数接收三个参数：要连接的URL，在接收到数据时调用的函数以及关闭连接时调用的函数。<br>只要readystatechange事件发生，而且readyState值为3，就对responseText进行分割以取得最新数据。这里的received变量用于记录已经处理了多少个字符，每次readyState值为3时都递增。然后，通过progress回调函数来处理传入的新数据。而当readyState值为4时，则执行finished回调函数，传入响应返回的全部内容。</p>
<h2 id="服务器发送事件"><a href="#服务器发送事件" class="headerlink" title="服务器发送事件"></a>服务器发送事件</h2><p>SSE(Server-Sent Events) SSE API用于创建到服务器的单向链接，服务器通过这个连接可以发送任意数量的数据。服务器响应的MIME类型必须是text/event-stream，而且是浏览器中javascript API能解析格式输出。</p>
<ol>
<li>SSE API</li>
</ol>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> source = <span class="keyword">new</span> EventSource(<span class="string">"myevents.php"</span>);</span><br></pre></td></tr></table></figure>
<p>实例有个readyState属性，值为0表示正连接到服务器，值为1表示打开了连接，值为2表示关闭了连接。</p>
<p>事件：</p>
<ul>
<li>open： 建立连接时触发。</li>
<li>message： 从服务器接收到新事件时触发</li>
<li>error： 无法建立连接时触发。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">source.onmessage = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> data = event.data;</span><br><span class="line">    <span class="comment">//处理数据</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>服务器返回的数据保存在event.data中。</p>
<p>默认情况下，EventSource对象会保持与服务器的活动连接。如果连接断开，还会重新连接。这就意味着SSE适合长轮询和HTTP流。</p>
<p>关闭连接使用source.close();</p>
<ol start="2">
<li>事件流</li>
</ol>
<p>服务器事件会通过一个持久的HTTP响应发送，这个响应的MIME类型为text/event-stream。响应的格式是纯文本，最简单的情况是每个数据项都带有前缀data：</p>
<p>data：foo</p>
<p>data: bar</p>
<p>data: foo<br>data: bar</p>
<p>第一第二个事件流返回的event.data值分别为foo bar。<br>第三个返回foo/bar。<code>:</code>后面需要添加空格。</p>
<p>通过id： 前缀可以给特定的事件指定一个关联的ID。这个ID位于前后都可以</p>
<p>data: foo<br>id: 1</p>
<h2 id="Web-Sockets"><a href="#Web-Sockets" class="headerlink" title="Web Sockets"></a>Web Sockets</h2><p>全双工，双向通信。</p>
<p>URL模式由http://变为ws://，https://变为wss://</p>
<ol>
<li>Web Socket API</li>
</ol>
<p>实例一个WebSocket对象并传入要连接的URL：<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> socket = <span class="keyword">new</span> WebSocket(<span class="string">"ws://www.example.com/server.php"</span>);</span><br></pre></td></tr></table></figure></p>
<p>readyState属性：</p>
<ul>
<li>0 正在建立连接</li>
<li>1 已建立连接</li>
<li>2 正在关闭连接</li>
<li>3 已经关闭连接</li>
</ul>
<p>要关闭连接，可以在任何时候调用close方法</p>
<ol start="2">
<li>发送和接受数据</li>
</ol>
<p>使用send()方法并传入任意字符。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> socket = <span class="keyword">new</span> WebSocket(<span class="string">"ws://www.example.com/server.php"</span>);</span><br><span class="line">socket.send(<span class="string">"Hello World!"</span>);</span><br></pre></td></tr></table></figure></p>
<p>Web Sockets 只能发送纯文本数据，所以对于复杂的结构需要进行序列化。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> message = &#123;</span><br><span class="line">    time: <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line">    text: <span class="string">"Hello World"</span>;</span><br><span class="line">    clientId: <span class="string">"asdfp"</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">socket.send(<span class="built_in">JSON</span>.stringify(message));</span><br></pre></td></tr></table></figure></p>
<ol start="3">
<li>其他事件</li>
</ol>
<ul>
<li>open: 成功建立连接时触发。</li>
<li>error： 在发生错误时触发，连接不能持续。</li>
<li>close： 在连接关闭时触发。</li>
</ul>
<p>这三个事件中，只有close事件的event对象有额外的信息。<br>wasClean、code和reason。<br>分别表示：布尔值（是否明确关闭连接）、服务器返回的数值状态码和服务器发回的消息。</p>
<h1 id="安全"><a href="#安全" class="headerlink" title="安全"></a>安全</h1><p>CSRF(Cross-Site Request Forgery)</p>
<ul>
<li>要求以SSL连接来访问可以通过XHR请求的资源</li>
<li>要求每一次请求都要附带经过相应算法计算得到的验证码。</li>
</ul>
<h1 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h1><p>Ajax是无需刷新页面就能够从服务器取得数据的一种方法。</p>
<ul>
<li>负责Ajax运作的核心对象是XMLHttpRequest(XHR)对象</li>
<li>XHR对象由微软最早在IE5中引入，用于通过JavaScript从服务器取得XML数据</li>
</ul>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/读书笔记/" rel="tag"># 读书笔记</a>
          
            <a href="/tags/js高程/" rel="tag"># js高程</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2017/09/06/305/" rel="next" title="js高程读书笔记 第18章 JavaScript与XML">
                <i class="fa fa-chevron-left"></i> js高程读书笔记 第18章 JavaScript与XML
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2017/09/08/310/" rel="prev" title="js高程读书笔记 第22章 高级技巧">
                js高程读书笔记 第22章 高级技巧 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/avatar.jpg" alt="何米酥">
            
              <p class="site-author-name" itemprop="name">何米酥</p>
              <p class="site-description motion-element" itemprop="description">Just do...</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">202</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">8</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">78</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/hemisu" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://www.zhihu.com/people/hemisu" target="_blank" title="知乎">
                      
                        <i class="fa fa-fw fa-globe"></i>知乎</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#本章内容"><span class="nav-number">1.</span> <span class="nav-text">本章内容</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#XMLHttpReques对象"><span class="nav-number">2.</span> <span class="nav-text">XMLHttpReques对象</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#XHR的用法"><span class="nav-number">2.1.</span> <span class="nav-text">XHR的用法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#HTTP头部信息"><span class="nav-number">2.2.</span> <span class="nav-text">HTTP头部信息</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#GET请求"><span class="nav-number">2.3.</span> <span class="nav-text">GET请求</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#POST请求"><span class="nav-number">2.4.</span> <span class="nav-text">POST请求</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#XMLHttpRequest-2级"><span class="nav-number">3.</span> <span class="nav-text">XMLHttpRequest 2级</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#FromData"><span class="nav-number">3.1.</span> <span class="nav-text">FromData</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#超时设定"><span class="nav-number">3.2.</span> <span class="nav-text">超时设定</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#overrideMimeType-方法"><span class="nav-number">3.3.</span> <span class="nav-text">overrideMimeType()方法</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#进度事件-Progress-Events"><span class="nav-number">4.</span> <span class="nav-text">进度事件 Progress Events</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#load事件"><span class="nav-number">4.1.</span> <span class="nav-text">load事件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#progress事件"><span class="nav-number">4.2.</span> <span class="nav-text">progress事件</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#跨资源共享-CORS"><span class="nav-number">5.</span> <span class="nav-text">跨资源共享 CORS</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#IE对CORS的实现"><span class="nav-number">5.1.</span> <span class="nav-text">IE对CORS的实现</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#其他浏览器对CORS的实现"><span class="nav-number">5.2.</span> <span class="nav-text">其他浏览器对CORS的实现</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Preflighted-Reqeusts"><span class="nav-number">5.3.</span> <span class="nav-text">Preflighted Reqeusts</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#带凭据的请求"><span class="nav-number">5.4.</span> <span class="nav-text">带凭据的请求</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#跨浏览器的CORS"><span class="nav-number">5.5.</span> <span class="nav-text">跨浏览器的CORS</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#其他跨域技术"><span class="nav-number">6.</span> <span class="nav-text">其他跨域技术</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#图像ping"><span class="nav-number">6.1.</span> <span class="nav-text">图像ping</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JSONP-JSON-with-padding"><span class="nav-number">6.2.</span> <span class="nav-text">JSONP (JSON with padding)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#服务器发送事件"><span class="nav-number">6.3.</span> <span class="nav-text">服务器发送事件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Web-Sockets"><span class="nav-number">6.4.</span> <span class="nav-text">Web Sockets</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#安全"><span class="nav-number">7.</span> <span class="nav-text">安全</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#小结"><span class="nav-number">8.</span> <span class="nav-text">小结</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      
        <div class="back-to-top">
          <i class="fa fa-arrow-up"></i>
          
            <span id="scrollpercent"><span>0</span>%</span>
          
        </div>
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; 2015 &mdash; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">何米酥</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        







        
      </div>
    </footer>

    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
